package util

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
)

// Encrypt 加密
type Encrypt struct {
}

// NewEncrypt 初始化Encrypt
func NewEncrypt() *Encrypt {
	return &Encrypt{}
}

// PKCS7Padding Use PKCS7 to fill
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}

// PKCS7UnPadding PKCS7 unpadding
func PKCS7UnPadding(origData []byte) []byte {
	length := len(origData)
	unpadding := int(origData[length-1])
	return origData[:(length - unpadding)]
}

// MinaSignVerify 小程序签名验证
func (e *Encrypt) MinaSignVerify(rawData, sessionKey, sign string) bool {
	h := sha1.New()
	_, err := h.Write([]byte(rawData + sessionKey))
	if err != nil {
		return false
	}
	return hex.EncodeToString(h.Sum(nil)) == sign
}

// MinaAESDecrypt 小程序解密
func (e *Encrypt) MinaAESDecrypt(encryptedData, sessionKey, iv string) ([]byte, error) {
	BEncryptedData, err := base64.StdEncoding.DecodeString(encryptedData)
	if err != nil {
		return nil, err
	}
	bIv, err := base64.StdEncoding.DecodeString(iv)
	if err != nil {
		return nil, err
	}
	bKey, err := base64.StdEncoding.DecodeString(sessionKey)
	if err != nil {
		return nil, err
	}

	block, err := aes.NewCipher(bKey)
	if err != nil {
		return nil, err
	}

	mode := cipher.NewCBCDecrypter(block, bIv)
	mode.CryptBlocks(BEncryptedData, BEncryptedData)
	return PKCS7UnPadding(BEncryptedData), nil
}

// SignSha256 sha256 签名计算
func SignSha256(sign string) (string, error) {
	h := sha256.New()
	_, err := h.Write([]byte(sign))
	if err != nil {
		return "", err
	}
	return hex.EncodeToString(h.Sum(nil)), nil
}
